
;window.Teamlab = (function () {
  var
    isInit = false,
    validSession = true,
    eventManager = null;

  var anchors = {
    auth        : /^auth[\/]*$/,
    index       : /^home[\/]*$/,
    tasklists   : /^tasklists[\/]*$/,
    task        : /^tasks\/([\w\d-]+)$/,
    discussions : /^discussions[\/]*$/,
    discussion  : /^discussions\/([\w\d-]+)$/
  }

  var staticanchors = {
    auth        : 'auth',
    index       : 'home',
    dashboard   : 'dashboard',
    milestones  : 'milestones',
    tasklists   : 'tasklists',
    documents   : 'documents',
    discussions : 'discussions'
  };

  var pageMenuItems = [
    {classname : 'dashboard',   title : 'Dashboard',    link : staticanchors.index,       isActive : false, led : 0},
    {classname : 'milestones',  title : 'Milestones',   link : staticanchors.milestones,  isActive : false, isUnavailable : true, led : 0},
    {classname : 'tasklists',   title : 'Tasklists',    link : staticanchors.tasklists,   isActive : false, led : 2},
    {classname : 'documents',   title : 'Documents',    link : staticanchors.documents,   isActive : false, isUnavailable : true, led : 0},
    {classname : 'discussions', title : 'Discussions',  link : staticanchors.discussions, isActive : false, led : 0}
  ];

  var customEvents = {
    getException      : 'ongetexception',
    getAuthentication : 'ongetauthentication',

    addComment    : 'onaddcomment',
    updateComment : 'onupdatecomment',
    removeComment : 'onremovecomment',

    getCmtBlog : 'ongetcmtyblog',

    addPrjComment     : 'onaddprjcomment',
    updatePrjComment  : 'onupdateprjcomment',
    removePrjComment  : 'onremoveprjcomment',
    addPrjTask        : 'onaddprjtask',
    getPrjTask        : 'ongetprjtask',
    getPrjTasks       : 'ongetprjtasks',
    getPrjDiscussion  : 'ongetprjdiscussion',
    getPrjDiscussions : 'ongetprjdiscussions',
    getPrjProjects    : 'ongetprjprojects',

    dashboardAnch   : 'ondashboardanch',
    taskAnch        : 'ontaskanch',
    tasklistsAnch   : 'ontasklistssanch',
    discussionAnch  : 'ondiscussionanch',
    discussionsAnch : 'ondiscussionsanch',

    changePage      : 'onchangepage',
    authPage        : 'onauthpage',
    indexPage       : 'onindexpage'
  }
  eventManager = new CustomEvent(customEvents);

  function clone (o) {
    if (!o || typeof o !== 'object') {
      return o;
    }

    var p, v, c = typeof o.pop === 'function' ? [] : {};
    for (p in o) {
      if (o.hasOwnProperty(p)) {
        v = o[p];
        if (v && typeof v === 'object') {
          c[p] = clone(v);
        } else {
          c[p] = v;
        }
      }
    }
    return c;
  }

  function callMethodByName (handlername, container, self, args) {
    handlername = handlername.replace(/-/g, '_');
	  if (container && typeof container === 'object' && typeof container[handlername] === 'function') {
		  container[handlername].apply(self, args);
		}
  }

  var init = function () {
    if (isInit === true) {
      return undefined;
    }
    isInit = true;

    AnchorController.bind(onAnch);

    AnchorController.bind(anchors.auth, onAuthAnch);

    AnchorController.bind(null,               onDashboardAnch);
    AnchorController.bind(anchors.index,      onDashboardAnch);
    AnchorController.bind(anchors.dashboard,  onDashboardAnch);

    AnchorController.bind(anchors.tasklists,  onTasklistsAnch);
    AnchorController.bind(anchors.task,       onTaskAnch);

    AnchorController.bind(anchors.discussions,  onDiscussionsAnch);
    AnchorController.bind(anchors.discussion,   onDiscussionAnch);

    ServiceManager.bind(null, onGetResponse);
    ServiceManager.bind('me', onGetOwnProfile);
    ServiceManager.bind('extention', onGetExtention);
    ServiceManager.bind('authentication', onGetAuthentication);
    ServiceManager.bind('unauthenticated', onGetUnauthenticated);

    ServiceManager.bind(customEvents.getCmtBlog, onGetCmtBlog);

    ServiceManager.bind(customEvents.addPrjTask, onAddPrjTask);
    ServiceManager.bind(customEvents.getPrjTask, onGetPrjTask);
    ServiceManager.bind(customEvents.getPrjTasks, onGetPrjTasks);
    ServiceManager.bind(customEvents.getPrjDiscussion, onGetPrjDiscussion);
    ServiceManager.bind(customEvents.getPrjDiscussions, onGetPrjDiscussions);
    ServiceManager.bind(customEvents.getPrjProjects, onGetPrjProjects);

    validSession = ServiceManager.logged();
  };

  var bind = function (eventName, handler, params) {
    return eventManager.bind(eventName, handler, params);
  };

  var unbind = function (handlerId) {
    return eventManager.unbind(handlerId);
  };

  var call = function (eventName, self, args) {
    eventManager.call(eventName, self, args);
  };

  var extendEventManager = function (events) {
    for (var fld in events) {
      if (events.hasOwnProperty(fld)) {
        customEvents[fld] = events[fld];
      }
    }
    eventManager.extend(customEvents);
  };

  function onGetExtention (eventname, params, errors) {
    console.log('teamlab.onGetExtention: ', arguments);
  }

  function onGetResponse (params, obj) {
    if (params.hasOwnProperty('___handler') && params.hasOwnProperty('___container')) {
      var args = [params];
      for (var i = 1, n = arguments.length; i < n; i++) {
        args.push(arguments[i]);
      }
      callMethodByName(params.___handler, params.___container, this, args);
    }
  }

  function onGetAuthentication (params, obj) {
    validSession = true;
    AnchorController.move(staticanchors.index);
  }

  function onGetUnauthenticated () {
    validSession = false;
    AnchorController.move(staticanchors.auth);
  }

  function onGetOwnProfile (params, profile) {
    //console.log('me: ', profile);
  }

  function onGetCmtBlog (params, blog) {
    //console.log('teamlab.onGetCmtBlog: ', blog);
  }

  function onAddPrjTask (params, task) {
    //console.log('teamlab.onAddPrjTask: ', task);
  }

  function onGetPrjTask (params, task) {
    console.log('teamlab.onGetPrjTask: ', task);
  }

  function onGetPrjTasks (params, tasks) {
    //console.log('teamlab.onGetPrjTasks: ', tasks);
  }

  function onGetPrjDiscussion (params, discussion, comments) {
    //console.log('teamlab.onGetPrjDiscussion: ', discussion, comments);
  }

  function onGetPrjDiscussions (params, discussions) {
    //console.log('teamlab.onGetPrjDiscussions: ', discussions);
  }

  function onGetPrjProjects (params, projects) {
    //console.log('teamlab.onGetPrjProjects: ', projects);
  }

/* <anchors callbacks> */
  function onAnch (params) {
    //if (!window.pageTracker && window._gat) {
    //  try {window.pageTracker = _gat._getTracker('UA-12442749-7')} catch (err) {}
    //}

    //if (window.pageTracker) {
    //  try {window.pageTracker._trackPageview(anchor)} catch (err) {}
    //}
  }

  /*<auth>*/
  function onAuthAnch (params) {
    if (validSession) {
      AnchorController.move(staticanchors.index);
      return undefined;
    }

    eventManager.call(customEvents.changePage, window, []);
    eventManager.call(customEvents.authPage, window, [params]);
  }
  /*</auth>*/

  /*<dashboard>*/
  function onDashboardAnch (params) {
    if (!validSession) {
      onGetUnauthenticated();
      return undefined;
    }

    eventManager.call(customEvents.changePage, window, []);
    eventManager.call(customEvents.dashboardAnch, this, arguments);
  }
  /*</dashboard>*/

  /*<tasklists>*/
  function onTasklistsAnch (params) {
    if (!validSession) {
      onGetUnauthenticated();
      return undefined;
    }

    eventManager.call(customEvents.changePage, window, []);
    eventManager.call(customEvents.tasklistsAnch, this, arguments);
  }

  function onTaskAnch (params, id) {
    if (!validSession) {
      onGetUnauthenticated();
      return undefined;
    }

    eventManager.call(customEvents.changePage, window, []);
    eventManager.call(customEvents.taskAnch, this, arguments);
  }
  /*</tasklists>*/

  /*<onversations>*/
  function onDiscussionsAnch (params) {
    if (!validSession) {
      onGetUnauthenticated();
      return undefined;
    }

    eventManager.call(customEvents.changePage, window, []);
    eventManager.call(customEvents.discussionsAnch, this, arguments);
  }

  function onDiscussionAnch (params, id) {
    if (!validSession) {
      onGetUnauthenticated();
      return undefined;
    }

    eventManager.call(customEvents.changePage, window, []);
    eventManager.call(customEvents.discussionAnch, this, arguments);
  }
  /*</onversations>*/
/* </anchors callbacks> */

  var getPageMenu = function (activeitem, led) {
    var
      pagemenuitems = [],
      pageMenuItem = null,
      pageMenuItemsInd = pageMenuItems.length;

    while (pageMenuItemsInd--) {
      pageMenuItem = pageMenuItems[pageMenuItemsInd];
      if (activeitem === pageMenuItem.classname) {
        pagemenuitems.unshift(
          {
            classname : pageMenuItem.classname,
            title     : pageMenuItem.title,
            link      : pageMenuItem.link,
            isActive  : true,
            led       : led
          }
        );
        continue;
      }
      pagemenuitems.unshift(pageMenuItem);
    }
    return pagemenuitems;
  };

  var sortCommentsByTree = function (comments) {
    if (comments.length === 0) {
      return comments;
    }
    var tree = clone(comments), commentParentId = null, commentsInd = 0, ind = 0;

    commentsInd = tree ? tree.length : 0;
    while (commentsInd--) {
      commentParentId = tree[commentsInd].parentid;
      if (!tree[commentsInd].comments) {
        tree[commentsInd].comments = [];
      }
      if (commentParentId === null) {
          continue;
      }
      ind = tree.length;
      while (ind--) {
        if (tree[ind].id == commentParentId) {
          if (!tree[ind].comments) {
            tree[ind].comments = [];
          }
          tree[ind].comments.unshift(tree[commentsInd]);
          break;
        }
      }
    }

    commentsInd = tree ? tree.length : 0;
    while (commentsInd--) {
      if (tree[commentsInd].parentid !== null) {
        tree.splice(commentsInd, 1);
      }
    }

    return tree ? tree : comments;
  };

  var login = function (username, password) {
    return ServiceManager.login({}, username, password);
  };

  var getCmtBlog = function (params, id) {
    return ServiceManager.getCmtBlog(customEvents.getCmtBlog, params, id);
  };

  var addPrjComment = function (params, type, id, data) {
    var fn = null;
    switch (type.toLowerCase()) {
      case 'discussion' :
        fn = ServiceManager.addPrjDiscussionComment;
        break;
    }
    if (typeof fn === 'function') {
      return fn(customEvents.addPrjComment, params, id, data);
    }
    return false;
  };

  var updatePrjComment = function (params, type, id, data) {
    var fn = null;
    switch (type.toLowerCase()) {
      case 'discussion' :
        fn = ServiceManager.updatePrjDiscussionComment;
        break;
    }
    if (typeof fn === 'function') {
      return fn(customEvents.updatePrjComment, params, id, data);
    }
    return false;
  };

  var removePrjComment = function (params, type, id) {
    var fn = null;
    switch (type.toLowerCase()) {
      case 'discussion' :
        fn = ServiceManager.removePrjDiscussionComment;
        break;
    }
    if (typeof fn === 'function') {
      return fn(customEvents.removePrjComment, params, id);
    }
    return false;
  };

  var addPrjTask = function (tasktitle, projectid, responsibleid) {
    return true;
  };

  var getPrjTask = function (params, id) {
    return ServiceManager.getPrjTask(customEvents.getPrjTask, params, id);
  };

  var getPrjTasks = function (params, projectid) {
    return ServiceManager.getPrjTasks(customEvents.getPrjTasks, params, projectid);
  };

  var getPrjDiscussion = function (params, id) {
    return ServiceManager.getPrjDiscussion(customEvents.getPrjDiscussion, params, id);
  };

  var getPrjDiscussions = function (params, projectid) {
    return ServiceManager.getPrjDiscussions(customEvents.getPrjDiscussions, params, projectid);
  };

  var getPrjProjects = function (params) {
    ServiceManager.getPrjProjects(customEvents.getPrjProjects, params);
  };

  var getPrjSelfProjects = function (params) {
    ServiceManager.getPrjSelfProjects(customEvents.getPrjProjects, params);
  };

  return {
    events : customEvents,

    init                : init,
    bind                : bind,
    unbind              : unbind,
    call                : call,
    extendEventManager  : extendEventManager,

    getPageMenu         : getPageMenu,
    sortCommentsByTree  : sortCommentsByTree,

    login : login,

    getCmtBlog  : getCmtBlog,

    addPrjComment       : addPrjComment,
    updatePrjComment    : updatePrjComment,
    removePrjComment    : removePrjComment,
    addPrjTask          : addPrjTask,
    getPrjTask          : getPrjTask,
    getPrjTasks         : getPrjTasks,
    getPrjDiscussion    : getPrjDiscussion,
    getPrjDiscussions   : getPrjDiscussions,
    getPrjProjects      : getPrjProjects,
    getPrjSelfProjects  : getPrjSelfProjects
  };
})();
